<template>
  <div class="vc-alpha">
    <div class="vc-alpha-checkboard-wrap">
      <check-board></check-board>
    </div>
    <div class="vc-alpha-gradient" :style="{background: gradientColor}"></div>
    <div class="vc-alpha-container" ref="container"
         @mousedown="handleMouseDown"
         @touchmove="handleChange"
         @touchstart="handleChange">
      <div class="vc-alpha-pointer" :style="{left: colors.a * 100 + '%'}">
        <div class="vc-alpha-picker"></div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, ref, Ref } from 'vue'
import CheckBoard from './CheckBoard.vue'

export default defineComponent({
  name: 'Alpha',
  components: { CheckBoard },
  props: {
    colors: {
      type: Object,
      required: true
    },
  },
  emits: ['change'],
  setup(props, { emit }) {
    const container: Ref = ref(null)

    const handleChange = (e: Event, skip = false) => {
      !skip && e.preventDefault()
      const containerElement = container.value
      if (!container) {
        // for some edge cases, container may not exist. see #220
        return
      }
      const containerWidth = containerElement.clientWidth

      const xOffset = containerElement.getBoundingClientRect().left + window.scrollX
      const pageX = (e as any).pageX || ((e as any).touches ? (e as any).touches[0].pageX : 0)
      const left = pageX - xOffset

      let a
      if (left < 0) {
        a = 0
      } else if (left > containerWidth) {
        a = 1
      } else {
        a = Math.round(left * 100 / containerWidth) / 100
      }

      if (props.colors.a !== a) {
        emit('change', {
          h: props.colors.hsl.h,
          s: props.colors.hsl.s,
          l: props.colors.hsl.l,
          a: a,
          source: 'rgba',
        })
      }
    }

    const handleMouseDown = (e: MouseEvent) => {
      handleChange(e, true)
      window.addEventListener('mousemove', handleChange)
      window.addEventListener('mouseup', handleMouseUp)
    }

    const handleMouseUp = () => {
      unbindEventListeners()
    }

    const unbindEventListeners = () => {
      window.removeEventListener('mousemove', handleChange)
      window.removeEventListener('mouseup', handleMouseUp)
    }

    return {
      container,
      gradientColor: computed(() => {
        const rgba = props.colors.rgba
        const rgbStr = [rgba.r, rgba.g, rgba.b].join(',')
        return 'linear-gradient(to right, rgba(' + rgbStr + ', 0) 0%, rgba(' + rgbStr + ', 1) 100%)'
      }),
      handleChange,
      handleMouseDown,
    }
  },
})
</script>